/*****************************************************************************
  Copyright ?2002-2004 by Martin Cook. All rights are reserved. If you like
  this code then feel free to go ahead and use it. The only thing I ask is 
  that you don't remove or alter my copyright notice. Your use of this 
  software is entirely at your own risk. I make no claims about the 
  reliability or fitness of this code for any particular purpose. If you 
  make changes or additions to this code then please clearly mark your code 
  as yours. If you have questions or comments then please contact me at: 
  martin@codegator.com
  
  Have Fun! :o)
*****************************************************************************/

using System;
using System.Data;
using System.Security.Principal;

namespace CG.Security.Principal
{

	/// <summary>
	/// A custom principal with support for CG.Security features.
	/// </summary>
	public sealed class CustomPrincipal : System.Security.Principal.IPrincipal	
	{

		// ******************************************************************
		// Attributes.
		// ******************************************************************

		#region Attributes

		/// <summary>
		/// The collection of roles for the user.
		/// </summary>
		private string[] m_roles;

		/// <summary>
		/// The collection of rights for the user.
		/// </summary>
		private string[] m_rights;

		/// <summary>
		/// The identity of the user.
		/// </summary>
		private System.Security.Principal.IIdentity m_identity;

		#endregion

		// ******************************************************************
		// Constructors.
		// ******************************************************************
			
		#region Constructors

		/// <summary>
		/// Initializes a new instance of the CustomPrincipal class from a 
		/// IIdentity and an array of role names to which the user represented 
		/// by that IIdentity belongs.
		/// </summary>
		/// <param name="identity">A basic implementation of IIdentity that represents any user in the security database.</param>
		/// <param name="roles">An array of role names to which the user represented by the identity parameter belongs.</param>
		public CustomPrincipal(
			System.Security.Principal.IIdentity identity,
			string[] roles
			)
		{

			// Sanity check the identity before using it.
			if (identity == null)
				throw new ArgumentNullException(
					"identity",
					"Argument must not be null"
					);

			m_identity = identity;
			m_roles = roles;
			m_rights = null;

		} // End CustomPrincipal()

		// ******************************************************************

		/// <summary>
		/// Initializes a new instance of the CustomPrincipal class from a 
		/// IIdentity and an array of role names to which the user represented 
		/// by that IIdentity belongs.
		/// </summary>
		/// <param name="identity">A basic implementation of IIdentity that represents any user in the security database.</param>
		/// <param name="roles">An array of role names to which the user represented by the identity parameter belongs.</param>
		/// <param name="rights">An array of right names to which the user represented by the identity parameter is entitled.</param>
		public CustomPrincipal(
			System.Security.Principal.IIdentity identity,
			string[] roles,
			string[] rights
			)
		{

			// Sanity check the identity before using it.
			if (identity == null)
				throw new ArgumentNullException(
					"identity",
					"Argument must not be null"
					);

			m_identity = identity;
			m_roles = roles;
			m_rights = rights;

		} // End CustomPrincipal()

		// ******************************************************************

		/// <summary>
		/// Initializes a new instance of the CustomPrincipal class from a 
		/// IIdentity and an array of role names to which the user represented 
		/// by that IIdentity belongs.
		/// </summary>
		/// <param name="identity">A CustomIdentity that represents any user in the security database.</param>
		public CustomPrincipal(
			CustomIdentity identity
			)
		{

			// Sanity check the identity before using it.
			if (identity == null)
				throw new ArgumentNullException(
					"identity",
					"Argument must not be null"
					);

			m_identity = identity;

			// Find the roles for the user.
			DataSet ds = UserRoleManager.FindByUser(
				identity.UserID
				);

			// Create an array to contain the role names.
			int roleCount = ds.Tables[0].Rows.Count;
			m_roles = new string[roleCount];
			
			// Loop and copy the role names.
			for (int x = 0; x < roleCount; x++)
				m_roles[x] = (string)ds.Tables[0].Rows[x]["role_name"];

			// Get the collection of rights.
			m_rights = SecurityManager.EffectiveRights(
				identity.UserID);

		} // End CustomPrincipal()

		#endregion

		// ******************************************************************
		// IPrincipal implementation.
		// ******************************************************************

		#region IPrincipal implementation

		/// <summary>
		/// Determines whether the current CustomPrincipal belongs to the specified role.
		/// </summary>
		/// <param name="roleName"></param>
		/// <returns></returns>
		public bool IsInRole(
			string roleName
			)
		{
			return m_roles != null && Array.IndexOf(m_roles, roleName) >= 0;
		} // End IsInRole()

		// ******************************************************************

		/// <summary>
		/// Gets the identity of the user represented by the current CustomPrincipal.
		/// </summary>
		public System.Security.Principal.IIdentity Identity
		{
			get {return m_identity;}
		} // End Identity

		#endregion

		// ******************************************************************
		// Public methods.
		// ******************************************************************

		#region Public methods
		
		/// <summary>
		/// Determines whether the current CustomPrincipal is entitled to the specified right.
		/// </summary>
		/// <param name="rightName"></param>
		/// <returns></returns>
		public bool IsAuthorized(
			string rightName
			)
		{
			return m_rights != null && Array.IndexOf(m_rights, rightName) >= 0;
		} // End IsAuthorized()

		#endregion

	} // End class CustomPrincipal

} // End namespace CG.Security.Principal

